package com.ds.infrastructure.audit.collector.security;

import com.ds.infrastructure.audit.collector.entity.UserInfo;
import com.ds.infrastructure.audit.collector.enums.Role;
import com.ds.infrastructure.audit.collector.service.SSOService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * 作用：
 *
 * @author WeiShaoying
 * @date 2020/8/10
 */
@Component
@Slf4j
public class SSOAuthenticationProvider implements AuthenticationProvider {

    @Resource
    private SSOService ssoService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SidAuthenticationToken sidAuthenticationToken = (SidAuthenticationToken) authentication;
        String sid = sidAuthenticationToken.getSid();

        if (StringUtils.isEmpty(sid)) {
            return anonymousToken();
        } else {
            try {
                UserInfo userInfo = ssoService.getUserInfo(sid);
                if (userInfo == null) {
                    return new SidAuthenticationToken(null, null);
                }
                List<GrantedAuthority> authorities = getAuthority(userInfo.getAuthority());
                log.info("用户信息: {}", userInfo);

                SidAuthenticationToken authenticationToken = new SidAuthenticationToken(userInfo, authorities);
                authenticationToken.setDetails(authentication.getDetails());
                return authenticationToken;
            } catch (BadCredentialsException e) {
                log.error("认证失败:{}", e.getMessage());
                return anonymousToken();
            } catch (Exception e) {
                log.error("认证异常:{}", e.getMessage(), e);
                return anonymousToken();
            }
        }
    }

    private List<GrantedAuthority> getAuthority(List<Role> roleList) {
        List<GrantedAuthority> grantedAuthorities = Lists.newArrayList();
        for (Role role : roleList) {
            setList(grantedAuthorities, role);
        }
        return grantedAuthorities;
    }

    private void setList(List<GrantedAuthority> grantedAuthorities, Role role) {
        switch (role) {
            case ROLE_ANONYMOUS:
                grantedAuthorities.add(new SimpleGrantedAuthority(Role.ROLE_ANONYMOUS.name()));
                break;
            case ROLE_USER:
                grantedAuthorities.add(new SimpleGrantedAuthority(Role.ROLE_USER.name()));
                break;
            case ROLE_ADMIN:
                grantedAuthorities.add(new SimpleGrantedAuthority(Role.ROLE_ADMIN.name()));
                break;
            default:
                break;
        }
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return SidAuthenticationToken.class.isAssignableFrom(clazz);
    }

    private List<GrantedAuthority> getAuthority(Role role) {
        List<GrantedAuthority> grantedAuthorities = Lists.newArrayList();
        setList(grantedAuthorities, role);
        log.info("grantedAuthorities={}", grantedAuthorities);
        return grantedAuthorities;
    }

    private SidAuthenticationToken anonymousToken() {
        List<GrantedAuthority> list = Lists.newArrayList(new SimpleGrantedAuthority(Role.ROLE_ANONYMOUS.name()));
        return new SidAuthenticationToken(null, list);
    }

}
